package com.axonactive.yolo.dto;

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

import org.apache.log4j.Logger;

import com.axonactive.yolo.service.interfaces.ExchangeRateService;
import com.axonactive.yolo.util.CONSTANTS;
import com.axonactive.yolo.util.Utils;

public class Flight {

	private static final Logger LOGGER = Logger.getLogger(Flight.class);

	private int id;
	private Price price;
	private OutBound outBound;
	private InBound inBound;
	private Parameters param;
	private String signature = "";
	private String flightId = "";
	private int checkSubscribe;
	private List<Provider> providers;
	
	public Flight() {
		
	}
	
	public Flight(Flight flight) {
		this.id = flight.id;
		this.price = flight.price;
		this.outBound = flight.outBound;
		this.inBound = flight.inBound;
		this.param = flight.param;
		this.signature = flight.signature;
		this.flightId = flight.flightId;
		this.checkSubscribe = flight.checkSubscribe;
		this.providers = flight.providers;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Parameters getParam() {
		return param;
	}

	public void setParam(Parameters param) {
		this.param = param;
	}

	public Price getPrice() {
		return price;
	}

	public void setPrice(Price price) {
		this.price = price;
	}

	public OutBound getOutBound() {
		return outBound;
	}

	public void setOutBound(OutBound outBound) {
		this.outBound = outBound;
	}

	public InBound getInBound() {
		return inBound;
	}

	public void setInBound(InBound inBound) {
		this.inBound = inBound;
	}

	public int getCheckSubscribe() {
		return checkSubscribe;
	}

	public void setCheckSubscribe(int checkSubscribe) {
		this.checkSubscribe = checkSubscribe;
	}

	public List<Provider> getProviders() {
		return providers;
	}

	public void setProviders(List<Provider> providers) {
		this.providers = providers;
	}

	/**
	 * Check flight has type of trip is oneway or roundtrip
	 * 
	 * @param flight
	 * @return true if roundtrip, otherwise return false
	 */
	public boolean isRoundTrip() {
		return this.getInBound() != null;
	}

	/**
	 * Get list of carrier in both outbound and inbound
	 * 
	 * @return
	 */
	public List<String> getListCarrier() {
		List<String> rs = new ArrayList<String>();
		// Get list of carriers of outbound
		List<AirportDeparture> airportDepartures = this.getOutBound()
				.getDepartAirports();
		for (Iterator<AirportDeparture> iterator = airportDepartures.iterator(); iterator
				.hasNext();) {
			AirportDeparture airportDeparture = (AirportDeparture) iterator
					.next();
			rs.add(airportDeparture.getAirline().getFlightNumber()
					.substring(0, 2));
		}
		// Get list of carriers of inbound
		if (isRoundTrip()) {
			List<AirportDeparture> airportDeparturesIB = this.getInBound()
					.getDepartAirports();
			for (Iterator<AirportDeparture> iterator = airportDeparturesIB
					.iterator(); iterator.hasNext();) {
				AirportDeparture airportDeparture = (AirportDeparture) iterator
						.next();
				rs.add(airportDeparture.getAirline().getFlightNumber()
						.substring(0, 2));
			}
		}
		return rs;
	}

	/**
	 * Create a string was combined by departure time, arrival time, carrier and
	 * stops of inbound
	 * 
	 * @return departureTime#$#arrivalTime#$#carriers#$#stops
	 */
	private String createInBoundSignature() {
		InBound out = this.getInBound();
		if (out == null)
			return "";
		if (this.getOutBound() == null) {
			return "";
		} else {
			String departureTime = out.getDepartAirports().get(0)
					.getDepartureTime();
			String arrivalTime = out.getArriveAirports()
					.get(out.getArriveAirports().size() - 1).getArrivalTime();
			String carrier = "";
			List<AirportDeparture> departureAirports = out.getDepartAirports();
			for (Iterator<AirportDeparture> iterator = departureAirports
					.iterator(); iterator.hasNext();) {
				AirportDeparture airportDeparture = (AirportDeparture) iterator
						.next();
				carrier = airportDeparture.getAirline().getFlightNumber();
			}
			String stops = out.getNumberStops();
			return departureTime + CONSTANTS.DELIMITER + arrivalTime
					+ CONSTANTS.DELIMITER + carrier + CONSTANTS.DELIMITER
					+ stops;
		}
	}

	/**
	 * Create a string was combined by departure time, arrival time, carriers
	 * and stops of outbound
	 * 
	 * @return departureTime#$#arrivalTime#$#carriers#$#stops;
	 */
	private String createOutBoundSignature() {
		OutBound out = this.getOutBound();
		if (out == null) {
			return "";
		} else {
			String departureTime = out.getDepartAirports().get(0)
					.getDepartureTime();
			String arrivalTime = out.getArriveAirports()
					.get(out.getArriveAirports().size() - 1).getArrivalTime();
			String carrier = "";
			List<AirportDeparture> departureAirports = out.getDepartAirports();
			for (Iterator<AirportDeparture> iterator = departureAirports
					.iterator(); iterator.hasNext();) {
				AirportDeparture airportDeparture = (AirportDeparture) iterator
						.next();
				carrier = airportDeparture.getAirline().getFlightNumber();
			}
			String stops = out.getNumberStops();
			return departureTime + CONSTANTS.DELIMITER + arrivalTime
					+ CONSTANTS.DELIMITER + carrier + CONSTANTS.DELIMITER
					+ stops;
		}
	}

	/**
	 * Create a string was combined by departure time, arrival time, carriers
	 * and stops of a flight
	 * 
	 * @return departureTimeOutBound#$#arrivalTimeOutBound#$#carriersOutBound#$#
	 *         stopsOutBound
	 *         %%%departureTimeInBound#$#arrivalTimeInBound#$#carriersInBound
	 *         #$#stopsInBound;
	 */
	public String getSignature() {
		if (signature == "") {
			signature = createOutBoundSignature() + "%%%"
					+ createInBoundSignature();
		}
		return signature;
	}

	public double getAmountPrice() {
		try {
			return Double.parseDouble(this.getPrice().getAmount());
		} catch (NumberFormatException e) {
			LOGGER.error("getAmountPrice parser exception", e);
			return 0;
		}
	}

	/**
	 * qtrung: we create an ID for the flight,it will combine: flight number,
	 * from-to location and departure date
	 * 
	 * @return id of the flight
	 */
	public String getFlightID() {
		if (flightId == "") {
			if (this.getOutBound() == null) {
				return "";
			}
			List<AirportDeparture> departAirports = new ArrayList<AirportDeparture>();
			departAirports = this.getOutBound().getDepartAirports();
			for (AirportDeparture airportDeparture : departAirports) {
				flightId += airportDeparture.getAirline().getFlightNumber()
						+ airportDeparture.getCode();
			}
			// get the destination location
			flightId += this.getOutBound().getArriveAirports()
					.get(this.getOutBound().getArriveAirports().size() - 1)
					.getCode();
			// get the departure day
			flightId += this.getOutBound().getDepartAirports().get(0)
					.getDepartureTimeByDDMMYY()
					+ CONSTANTS.DELIMITER;
			if (this.getInBound() != null) {
				departAirports = this.getInBound().getDepartAirports();
				for (AirportDeparture airportDeparture : departAirports) {
					flightId += airportDeparture.getAirline().getFlightNumber()
							+ airportDeparture.getCode();
				}
				flightId += this.getInBound().getArriveAirports()
						.get(this.getInBound().getArriveAirports().size() - 1)
						.getCode();
				flightId += this.getInBound().getDepartAirports().get(0)
						.getDepartureTimeByDDMMYY();
			}
			flightId += this.getOutBound().getDepartAirports().get(0)
					.getAirline().getFlightClass();
			return flightId;
		} else
			return flightId;
	}

	/**
	 * Get a flight by flightId in flight list
	 */
	public static Flight getFlightByFlightId(List<Flight> flights,
			String flightId) {
		for (Flight flight : flights) {
			if (flight.getFlightID().equals(flightId)) {
				return flight;
			}
		}
		return null;
	}

	public static List<TaskAlert> convertToTaskAlert(List<Flight> flights,
			boolean isRoundtrip) {
		List<TaskAlert> taskAlerts = new ArrayList<>();

		for (int i = 0; i < flights.size(); i++) {
			TaskAlert taskAlert = new TaskAlert();
			taskAlert.setId(i + "");
			taskAlert.setPrice(flights.get(i).getPrice().getAmount());
			taskAlert.setCurrencyCode(flights.get(i).getPrice()
					.getCurrencyCode());

			taskAlert.setCarrierO(flights.get(i).getOutBound()
					.getDepartAirports().get(0).getAirline().getName());
			taskAlert.setDepartureDateO(flights.get(i).getOutBound()
					.getDepartAirports().get(0).getDepartureTimeYYYYMMDD());
			taskAlert.setFromCodeO(flights.get(i).getOutBound()
					.getDepartAirports().get(0).getCode());
			taskAlert.setFromTimeO(flights.get(i).getOutBound()
					.getDepartAirports().get(0).getDepartureTimeByHHmm());
			taskAlert.setToCodeO(flights
					.get(i)
					.getOutBound()
					.getArriveAirports()
					.get(flights.get(i).getOutBound().getArriveAirports()
							.size() - 1).getCode());
			taskAlert.setToTimeO(flights
					.get(i)
					.getOutBound()
					.getArriveAirports()
					.get(flights.get(i).getOutBound().getArriveAirports()
							.size() - 1).getArrivalTimeByHHmm());
			taskAlert.setStopsO(flights.get(i).getOutBound().getNumberStops());
			taskAlert.setRoutO(flights.get(i).getOutBound()
					.getAirportsExpanded());

			if (isRoundtrip) {
				taskAlert.setCarrierI(flights.get(i).getInBound()
						.getDepartAirports().get(0).getAirline().getName());
				taskAlert.setDepartureDateI(flights.get(i).getInBound()
						.getDepartAirports().get(0).getDepartureTimeYYYYMMDD());
				taskAlert.setFromCodeI(flights.get(i).getInBound()
						.getDepartAirports().get(0).getCode());
				taskAlert.setFromTimeI(flights.get(i).getInBound()
						.getDepartAirports().get(0).getDepartureTimeByHHmm());
				taskAlert.setToCodeI(flights
						.get(i)
						.getInBound()
						.getArriveAirports()
						.get(flights.get(i).getInBound().getArriveAirports()
								.size() - 1).getCode());
				taskAlert.setToTimeI(flights
						.get(i)
						.getInBound()
						.getArriveAirports()
						.get(flights.get(i).getInBound().getArriveAirports()
								.size() - 1).getArrivalTimeByHHmm());
				taskAlert.setStopsI(flights.get(i).getInBound()
						.getNumberStops());
				taskAlert.setRoutI(flights.get(i).getInBound()
						.getAirportsExpanded());
			}

			taskAlerts.add(taskAlert);

		}
		
		// sort price
		for (int i = 0; i < taskAlerts.size(); i++) {
			for (int j = i+1; j < taskAlerts.size() - 1; j++) {
				if (Double.parseDouble(taskAlerts.get(i).getPrice()) > Double.parseDouble(taskAlerts.get(j).getPrice())) {
					TaskAlert taskAlert = taskAlerts.get(i);
					taskAlerts.set(i, taskAlerts.get(j));
					taskAlerts.set(j, taskAlert);
				}
			}
			taskAlerts.get(i).setId(i+"");
		}
		
		return taskAlerts;
	}
}
